package com.puzzlebazar.client.util;

import java.io.Serializable;

public class Recti implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 694706265503512387L;
	
	public int x;
	public int y;
	public int w;
	public int h;
	
	public Recti() {
		x = 0;
		y = 0;
		w = 0;
		h = 0;
	}
	
	public Recti(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}
	
	public Recti(Recti rect) {
		x = rect.x;
		y = rect.y;
		w = rect.w;
		h = rect.h;
	}
	
	/**
	 * Creates a rectangle given two diagonally opposed cells (or vertices). The first cell (vertex)
	 * can be any of the four corners of the rectangle, as long as the other is
	 * diagonally opposite. The rectangle produced include both corner cells (or vertices).
	 * 
	 * @param loc1 First cell (or vertex) of the rectangle
	 * @param loc2 Diagonally opposed cell (or vertex)
	 */
	public Recti(Vec2i loc1, Vec2i loc2) {
		x = Math.min(loc1.x, loc2.x);
		y = Math.min(loc1.y, loc2.y);
		w = Math.abs(loc2.x-loc1.x)+1;
		h = Math.abs(loc2.y-loc1.y)+1;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + h;
		result = prime * result + w;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Recti other = (Recti) obj;
		if (h != other.h)
			return false;
		if (w != other.w)
			return false;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	/**
	 * Modify this rectangle so that it is a copy of the passed rectangle
	 * 
	 * @param rect The rectangle to copy
	 */
	public void copy(Recti rect) {
		x = rect.x;
		y = rect.y;
		w = rect.w;
		h = rect.h;
	}
	
	/**
	 * @return The top-left corner vertex
	 */
	public Vec2i getPt00() {
		return new Vec2i( x, y );
	}
	
	/**
	 * @return The top-right corner vertex
	 */
	public Vec2i getPt10() {
		return new Vec2i( x+w, y );
	}

	/**
	 * @return The bottom-left corner vertex
	 */
	public Vec2i getPt01() {
		return new Vec2i( x, y+h );
	}	

	/**
	 * @return The bottom-right corner vertex
	 */
	public Vec2i getPt11() {
		return new Vec2i( x+w, y+h );
	}


	/**
	 * @return The top-left corner cell
	 */
	public Vec2i getCell00() {
		return new Vec2i( x, y );
	}
	
	/**
	 * @return The top-right corner cell
	 */
	public Vec2i getCell10() {
		return new Vec2i( x+w-1, y );
	}

	/**
	 * @return The bottom-left corner cell
	 */
	public Vec2i getCell01() {
		return new Vec2i( x, y+h-1 );
	}	

	/**
	 * @return The bottom-right corner cell
	 */
	public Vec2i getCell11() {
		return new Vec2i( x+w-1, y+h-1 );
	}	
	
	/**
	 * Checks if two rectangles overlap. Two rectangles overlapping only on a vertex
	 * or an edge are not considered to be overlapping by this function.
	 * 
	 * @param rect The second rectangle 
	 * @return true if the rectangles overlap, false otherwise
	 */
	public boolean overlap(Recti rect) {
		

		int left = x;
		int right = x+w-1;
		int top = y;
		int bottom = y+h-1;
		
		int bitfield = computeBitfield( rect.x, rect.y, left, right, top, bottom );
		bitfield &= computeBitfield( rect.x+rect.w-1, rect.y, left, right, top, bottom );
		bitfield &= computeBitfield( rect.x, rect.y+rect.h-1, left, right, top, bottom );
		bitfield &= computeBitfield( rect.x+rect.w-1, rect.y+rect.h-1, left, right, top, bottom );
		
		return bitfield == 0;
	}

	/**
	 * Return the Cohen-Sutherland bitfield code for point x, y
	 * Bit 0: Vertex is left of the left edge
	 * Bit 1: Vertex is right of the right edge
	 * Bit 2: Vertex is above top edge
	 * Bit 3: Vertex is below bottom edge
	 * 
	 * @param x  X-coord of point to check
	 * @param y  Y-coord of point to check
	 * @param left  Left coord of window
	 * @param right Right coord of window
	 * @param top Top coord of window
	 * @param bottom Bottom coord of window
	 * @return The bitfield code
	 */
	private int computeBitfield( int x, int y, int left, int right, int top, int bottom ) {
		int bitfield = 0;
		if( x < left ) bitfield |= 1;
		if( x > right ) bitfield |= 2;
		if( y < top ) bitfield |= 4;
		if( y > bottom ) bitfield |= 8;
		return bitfield;
	}

	/**
	 * Checks if a given cell is contained with the rectangle
	 * 
	 * @param cellLoc location of the cell
	 * @return True if the passed cell is inside the rectangles, false otherwise
	 */
	public boolean contains(Vec2i cellLoc) {
		return 
			cellLoc.x >= x && cellLoc.x < x+w &&
			cellLoc.y >= y && cellLoc.y < y+h;
	}

	
}